How can I make a block only be placed on certain other blocks

From the wiki, about Item NBT tags :

Blocks can be given tags to specify what blocks they may be placed against in Adventure mode [...]

tag: The tag tag.
- CanPlaceOn: Determines which blocks that blocks with this tag can be placed against in adventure mode.

As the give command takes the Item's tag tag as last parameter, you just have to drop your list of blocks in there :

// Give one block of stone that can be placed on grass or dirt
give @p minecraft:stone 1 0 {CanPlaceOn:["minecraft:grass","minecraft:dirt"]}

Or, in 1.13+:

give @p stone{CanPlaceOn:["minecraft:grass","minecraft:dirt"]}